import os
import re
import io
import gc
import pandas as pd
from datetime import datetime
from PIL import Image
from docx import Document
from openpyxl import load_workbook
from olefile import OleFileIO
from django.conf import settings
from .models import Question
from .utils import get_subject_pinyin, determine_question_type, get_max_id, combine_images_horizontally, pattern_question_title, pattern_question_options

def parse_excel(file_path):
    # 读取Excel文件，包括图片
    questions = []
    image_folder = os.path.join(settings.MEDIA_ROOT, 'question_images')
    os.makedirs(image_folder, exist_ok=True)  # 确保图片目录存在

    excel_obj = None
    df = None

    try:
        # 读取Excel数据
        df = pd.read_excel(file_path)

        # 使用openpyxl打开文件以处理图片
        wb = load_workbook(file_path)
        ws = wb.active

        # 获取所有图片及其位置信息
        image_dict = {}  # 用于存储图片位置信息 {(row, col): [image_data_list]}

        # 处理插入到单元格上方的图片
        for image in ws._images:
            # openpyxl中图片位置是从0开始计数的
            row = image.anchor._from.row + 1  # 转换为从1开始计数
            col = image.anchor._from.col + 1  # 转换为从1开始计数

            # 初始化该位置的图片列表（如果不存在）
            if (row, col) not in image_dict:
                image_dict[(row, col)] = []

            # 添加图片到列表
            image_dict[(row, col)].append(('above', image))
        # 因为暂时没有找到好的办法处理插入到单元格内的图片，所以暂时不支持Excel中插入到单元格内的图片。
        # 所以如果是Excel文件中有插入到单元格内的图片，则会导致图片无法正常导入到题库中。

        print(f"找到 {sum(len(images) for images in image_dict.values())} 张图片")

        for idx, row_data in df.iterrows():
            # Excel中的行号，考虑表头，从2开始（第一行是表头）
            excel_row = idx + 2  # 加2是因为Excel行从1开始，且有表头

            # 获取图片单元格的位置
            image_path = None
            image_name = None

            try:
                # 检查'图片'列是否存在
                if '图片' in df.columns:
                    img_col = df.columns.get_loc('图片') + 1  # 转换为从1开始的列号

                    # 检查单元格位置是否有图片
                    if (excel_row, img_col) in image_dict and image_dict[(excel_row, img_col)]:
                        image_paths = []  # 存储所有图片路径

                        # 处理该单元格的所有图片
                        for img_idx, (img_type, img_data) in enumerate(image_dict[(excel_row, img_col)]):
                            # 生成唯一的图片名称
                            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
                            image_name = f"{timestamp}_{idx}_{img_idx}.png"  # 使用PNG格式保存
                            dest_path = os.path.join(image_folder, image_name)

                            try:
                                # 根据图片类型处理数据
                                if img_type == 'above':
                                    # 处理插入到单元格上方的图片
                                    img_binary = img_data._data()
                                else:
                                    raise ValueError(f"未知的图片类型: {img_type}")

                                # 保存图片
                                with open(dest_path, 'wb') as img_file:
                                    img_file.write(img_binary)

                                # 设置相对路径（相对于MEDIA_ROOT的路径，用于数据库存储）
                                image_path = os.path.join('question_images', image_name)
                                image_paths.append(image_path)
                                print(f"成功保存{img_type}类型图片: {image_path}")
                                print(f"完整图片路径: {os.path.join(settings.MEDIA_ROOT, image_path)}")
                                print(f"图片URL路径: {os.path.join(settings.MEDIA_URL, image_path)}")

                            except Exception as e:
                                print(f"保存第{img_idx + 1}张图片时出错: {str(e)}")
                                continue

                        # 如果只有一张图片，直接使用
                        if len(image_paths) == 1:
                            image_path = image_paths[0]
                            image_name = os.path.basename(image_paths[0])
                else:
                    print("Excel文件中没有'图片'列")
            except Exception as e:
                print(f"处理第{idx + 1}行图片时出错: {str(e)}")

            # 构建题目数据
            question_data = {
                'content': row_data['题干'],
                'options': row_data['选项'],
                'answer': row_data['答案'],
                'image': image_path,  # 存储相对路径
                'image_name': image_name,  # 存储图片名
                'difficulty': row_data['难度']
            }

            # 添加科目和题型字段，处理可能不存在的列
            if '科目' in df.columns:
                question_data['subject'] = row_data['科目']
            else:
                question_data['subject'] = '默认科目'

            if '题型' in df.columns:
                question_data['question_type'] = row_data['题型']
            else:
                # 根据选项和答案自动判断题型
                question_data['question_type'] = determine_question_type(row_data['选项'], row_data['答案'])

            questions.append(question_data)

        print(f"总共处理了 {len(questions)} 个问题")

    except Exception as e:
        print(f"解析Excel文件时出错: {str(e)}")
        raise e
    finally:
        # 确保资源被释放
        if 'wb' in locals():
            wb.close()

        # 强制释放pandas资源
        df = None

        # 建议垃圾回收
        gc.collect()

    return questions

# 预览WORD文件
def parse_word(file_path):
    try:
        doc = Document(file_path)
    except Exception as e:
        raise ValueError("无法打开Word文件")
    questions = []
    current_question = ''
    current_options = []
    # 遍历Word文档中的每一个段落
    for para in doc.paragraphs:
        text = para.text.strip()
        print(text)
        if not text:
            continue

        # 题干行
        if text.startswith('题干：'):
            current_question = text.replace('题干：', '').strip()
            continue

        # 选项行（以A.、B.、C.等开头）
        if re.match(pattern_question_options, text):
            current_options.append(text)
            continue

        current_answer = ''
        # 答案行（以"答案："开头）
        if text.startswith('答案：'):
            current_answer = text.replace('答案：', '').strip()

            options_str = '\n'.join(current_options) if current_options else ''
            questions.append({
                'subject': '1',
                'content': current_question,
                'question_type': determine_question_type(options_str, current_answer),
                'options': options_str,
                'answer': current_answer,
                'difficulty': 'medium',
                'image': None  # 添加image字段，默认为None
            })
            current_question = ''
            current_options = []
    return questions

# 从Word文件导入题库
def import_from_word(this_file_path, subject_id):
    # 使用try-finally确保资源正确释放
    doc = None
    try:
        doc = Document(this_file_path)
        total_imported = 0
        type_counts = {'single': 0, 'multiple': 0, 'judge': 0}
        subject_pinyin = get_subject_pinyin(subject_id)
        image_folder = os.path.join(settings.MEDIA_ROOT, 'question_images')
        os.makedirs(image_folder, exist_ok=True)  # 创建图片保存文件夹

        current_image_paths = []  # 存储多张图片路径
        base_question_number = get_max_id()  # 从数据库中读取exam_system_question 表中的最大id值
        question_counter = 0  # 用于给每道题生成唯一的编号

        current_question = ''
        current_options = []
        current_answer = ''

        # 遍历Word文档中的每一个段落
        for para in doc.paragraphs:
            text = para.text.strip()
            print(text)
            # 处理图片
            if para.runs and para.runs[0].text == '' and para.runs[0].element.xpath('.//w:drawing'):
                question_number = base_question_number + question_counter
                image_name = f'{subject_pinyin}_{question_number}_{len(current_image_paths) + 1}.png'
                image_path = os.path.join(image_folder, image_name)
                for shape in para._element.xpath('.//w:drawing'):
                    blip = shape.xpath('.//a:blip/@r:embed')[0]
                    image_part = doc.part.related_parts[blip]
                    with open(image_path, 'wb') as f:
                        f.write(image_part.blob)
                current_image_paths.append(image_path)
                current_question += f'<img src="{settings.MEDIA_URL}question_images/{image_name}">'
                continue

            if not text:
                continue

            # 题干行
            if text.startswith('题干：'):
                current_question = text.replace('题干：', '').strip()
                continue

            # 选项行（以A.、B.、C.等开头）
            if re.match(pattern_question_options, text):
                current_options.append(text)
                continue

            # 答案行（以"答案："开头）
            if text.startswith('答案：'):
                current_answer = text.replace('答案：', '').strip()
                if not current_answer:
                    current_question = ''
                    current_options = []
                    continue
                # 把当前题目导入进数据库，前提是题干和答案不为空
                if current_question and current_answer:
                    options_str = '\n'.join(current_options) if current_options else ''
                    question_type = determine_question_type(options_str, current_answer)
                    difficulty = 'medium'  # 默认难度
                    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

                    # 处理多张图片
                    question_number = base_question_number + question_counter
                    if len(current_image_paths) > 1:
                        combined_image_name = f'{subject_pinyin}_{question_number}_combined.png'
                        combined_image_path = os.path.join(image_folder, combined_image_name)
                        combine_images_horizontally(current_image_paths, combined_image_path)
                        final_image_path = combined_image_path
                    elif len(current_image_paths) == 1:
                        final_image_path = current_image_paths[0]
                    else:
                        final_image_path = None

                    Question.objects.create(
                        subject_id=subject_id,
                        content=current_question,
                        question_type=question_type,
                        options=options_str,
                        answer=current_answer,
                        difficulty=difficulty,
                        image=final_image_path,
                        create_time=current_time,
                        update_time=current_time
                    )

                    # 更新题目计数器
                    question_counter += 1

                    # 清空本题变量
                    current_question = ''
                    current_options = []
                    current_image_paths = []

                    total_imported += 1
                    type_counts[question_type] += 1

    finally:
        # 释放资源
        doc = None

        # 建议垃圾回收
        gc.collect()

    return total_imported